package pres.man.interview.producerconsumer.readwrite;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 读写者问题
 * 使用ReadWriteLock实现
 *
 * @author MAN
 * @date 2020-12-07 21:42
 * @project
 * @since
 */
public class ReadWrite {

    private static final ThreadPoolExecutor POOL = new ThreadPoolExecutor(5, 8, 20, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10), new ThreadPoolExecutor.CallerRunsPolicy());

    public static void main(String[] args) {
        ReadWrite readWrite = new ReadWrite();
        for (int i = 0; i < 5; i++) {
            POOL.execute(() -> {
                for (; ; ) {
                    readWrite.write();
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
            POOL.execute(() -> {
                for (; ; ) {
                    readWrite.write();
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
            POOL.execute(() -> {
                for (; ; ) {
                    readWrite.write();
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
            POOL.execute(() -> {
                for (; ; ) {
                    readWrite.read();
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
            POOL.execute(() -> {
                for (; ; ) {
                    readWrite.read();
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
            POOL.execute(() -> {
                for (; ; ) {
                    readWrite.read();
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });

        }

    }

    private static final ReadWriteLock LOCK = new ReentrantReadWriteLock();
    private static final Lock READ_LOCK = LOCK.readLock();
    private static final Lock WRITE_LOCK = LOCK.writeLock();

    /**
     * 读
     */
    public void read() {
        READ_LOCK.lock();
        try {
            System.out.println("read");
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            READ_LOCK.unlock();
        }
    }

    /**
     * 写
     */
    public void write() {
        WRITE_LOCK.lock();
        try {
            System.out.println("write");
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            WRITE_LOCK.unlock();
        }
    }
}
